package com.yc.xunlei1;
import org.apache.log4j.Logger;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;


public class Xunlei {
    private static Logger log=Logger.getLogger(Xunlei.class.getName());
    //private static volatile long fileSizeDownLoad=0;//不能保证龙的原子性
    //private static long fileSizeDownLoad=0;
    private static AtomicLong fileSizeDownLoad=new AtomicLong(0L);//保证原子性

    public static void main(String[] args) throws IOException, InterruptedException {
        List<Thread>list=new ArrayList<>();
        long start=System.currentTimeMillis();
        String url="https://download.imgo.tv/app/pc/6.7.16_1.1.43/mgtv-client-6.7.16.0-mango.exe";
        //1.获取下载文件的大小
        long fileSize=getDownLoadFileSize(url);
        log.info("待下载的文件大小："+fileSize);
        //2.新文件保存的位置
        String newFileName=genFileName(url);
        log.info("下载后的文件名"+newFileName);
        String userhome=System.getProperty("user.home");
        String downloadPath=userhome+ File.separator +newFileName;
        log.info("下载后新的文件的地址"+downloadPath);
        //3.创建此新文件（空）
        RandomAccessFile raf=new RandomAccessFile(downloadPath,"rw");
        raf.setLength(fileSize);
        raf.close();
        log.info("空的新文件下载成功");
        //4.获取本机的核数=》线程数
       int threadSize=Runtime.getRuntime().availableProcessors();
       log.info("线程数"+threadSize);
       //5.计算每个线程要下载的字节数
       long sizePerThread=getSizePerThread(fileSize,threadSize);
       log.info("每个线程要下载的字节数"+sizePerThread);
       //6.循环创建线程，每个线程下载自己的部分
        for (int i=0;i<threadSize;i++){
           DownLoadPathSizeNotify dlsn=new DownLoadPathSizeNotify() {
               @Override
               public void notifySize(long size) {
                   //fileSizeDownLoad+=size;//不能保证原子性
//                   synchronized (Xunlei.class){
//                       fileSizeDownLoad+=size;
//                       System.out.println("已下载的文件总大小："+fileSizeDownLoad);
//                   }
                   //方案三：利用原子类型
                   fileSizeDownLoad.addAndGet(size);
                   System.out.println("已下载的文件总大小："+fileSizeDownLoad.get());//74,935,304
               }
           };
           DownLoadTask task=new DownLoadTask(i,fileSize,threadSize,sizePerThread,url,downloadPath,dlsn);
           Thread t=new Thread(task);
           t.start();
           list.add(t);
        }
        for (Thread t:list){
            t.join();
        }
        System.out.println("主线程阻塞在此，等待子线程执行完毕...");
        long end=System.currentTimeMillis();
        System.out.println("程序执行的总时长："+(end-start));

    }
    //正式下载前获取文件大小
    private static long getDownLoadFileSize(String url) throws IOException {
        long fileSize=0;
        URL u=new URL(url);
        HttpURLConnection connection=(HttpURLConnection) u.openConnection();
        //设置请求头
        connection.setRequestMethod("HEAD");
        connection.setConnectTimeout(3000);
        connection.connect();
        fileSize=connection.getContentLength();
        log.info("文件大小"+fileSize);
        return fileSize;
    }
    //根据日期和时间生成新文件的文件名
    private static String genFileName(String url) {
        Date d=new Date();
        DateFormat df=new SimpleDateFormat("yyMMddHHmmss");
        String prefix=df.format(d);
        //后缀名
        String suffix=url.substring(url.lastIndexOf("."));
        return prefix+suffix;

    }
    //计算每个线程要下载的字节数
    private static long getSizePerThread(long fileSize,int threadSize){
        return fileSize%threadSize==0?fileSize/threadSize:fileSize/threadSize+1;
    }
}
//下载数据量的回调接口
interface DownLoadPathSizeNotify{
    public void notifySize(long size);

}
